package com.peas.platform.module.icims.expenditure.kpis.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
import com.peas.platform.common.core.enums.BaseEnum;
import com.peas.platform.framework.mybatisplus.domain.BaseDomain;
import com.peas.platform.framework.mybatisplus.po.BasePo;
import com.peas.platform.framework.mybatisplus.service.BaseServiceImpl;
import com.peas.platform.module.icims.base.approve.component.ApproveCallback;
import com.peas.platform.module.icims.base.approve.dto.ApproveDto;
import com.peas.platform.module.icims.base.approve.dto.ApproveOrderNodeDto;
import com.peas.platform.module.icims.base.approve.enums.ApproveOrderBusinessType;
import com.peas.platform.module.icims.base.approve.service.ApproveOrderService;
import com.peas.platform.module.icims.base.approve.service.ApproveService;
import com.peas.platform.module.icims.expenditure.kpis.api.req.SaveExpenditureQuotaVo;
import com.peas.platform.module.icims.expenditure.kpis.api.req.SubmitExpenditureQuotaVo;
import com.peas.platform.module.icims.expenditure.kpis.domain.ExpenditureQuotaDomain;
import com.peas.platform.module.icims.expenditure.kpis.dto.ExpenditureKpiDto;
import com.peas.platform.module.icims.expenditure.kpis.dto.ExpenditureQuotaDto;
import com.peas.platform.module.icims.expenditure.kpis.enums.ExpenditureQuotaState;
import com.peas.platform.module.icims.expenditure.kpis.service.ExpenditureKpiService;
import com.peas.platform.module.icims.expenditure.kpis.service.ExpenditureQuotaService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;

@Service
public class ExpenditureQuotaServiceImpl extends BaseServiceImpl<ExpenditureQuotaDto> implements ExpenditureQuotaService, ApproveCallback {

    @Resource
    private ExpenditureQuotaDomain expenditureQuotaDomain;
    @Resource
    private ApproveService approveService;
    @Resource
    private ApproveOrderService approveOrderService;
    @Resource
    private ExpenditureKpiService expenditureKpiService;

    @Override
    public BaseDomain<ExpenditureQuotaDto, ? extends BasePo> getDomain() {
        return expenditureQuotaDomain;
    }

    @Transactional
    @Override
    public ExpenditureQuotaDto saveExpenditureQuota(SaveExpenditureQuotaVo vo) {
        ExpenditureQuotaDto eqd = BeanUtil.copyProperties(vo, ExpenditureQuotaDto.class);
        if (StrUtil.isBlank(eqd.getState())) {
            eqd.setState(ExpenditureQuotaState.save.getKey());
        }
        Assert.isTrue(vo.getAmount().compareTo(BigDecimal.ZERO) > 0, "下达金额必须大于0");
        Assert.notNull(vo.getExpenditureKpiId(), "请选择指标单");
        Long expenditureKpiId = vo.getExpenditureKpiId();
        if (expenditureKpiId != null) {
            BigDecimal totalQuotaAmount = expenditureKpiService.getTotalQuotaAmount(expenditureKpiId);
            BigDecimal totalAdjustAmount = expenditureKpiService.getTotalAdjustmentAmount(expenditureKpiId);
            ExpenditureKpiDto kpi = expenditureKpiService.getById(expenditureKpiId);
            Assert.isTrue(vo.getAmount().compareTo(kpi.getAmount().add(totalAdjustAmount).subtract(totalQuotaAmount)) <= 0, "指标单[{}]剩余可下达金额为:{}", kpi.getKpiCode(), NumberUtil.toStr(kpi.getAmount().subtract(totalQuotaAmount)));
        }
        int result;
        if (vo.getId() != null) {
            ExpenditureQuotaDto bean = this.getById(vo.getId());
            ExpenditureQuotaState state = BaseEnum.key2Enum(ExpenditureQuotaState.class, bean.getState());
            Assert.isTrue(ExpenditureQuotaState.save == state || ExpenditureQuotaState.revocation == state || ExpenditureQuotaState.reject == state, "额度下达单[" + bean.getQuotaCode() + "]的状态为[" + state.getKey() + "-" + state.getValue() + "]，不允许修改");
            result = this.updateById(eqd);
        } else {
            result = this.save(eqd);
        }
        Assert.isTrue(result > 0, "保存失败");
        Assert.isTrue(expenditureKpiService.queryAvailableAmount(expenditureKpiId).compareTo(BigDecimal.ZERO) >= 0, "下达金额不能超过指标单可用金额");
        return eqd;
    }

    @Transactional
    @Override
    public void submitExpenditureQuota(SubmitExpenditureQuotaVo vo) {
        Assert.notNull(vo.getApproveId(), "请选择审批模版");
        SaveExpenditureQuotaVo v = BeanUtil.copyProperties(vo, SaveExpenditureQuotaVo.class);
        v.setState(ExpenditureQuotaState.submit.getKey());
        ExpenditureQuotaDto ead = this.saveExpenditureQuota(v);
        ApproveDto ad = approveService.getById(vo.getApproveId());
        approveOrderService.createApproveOrder(ad, BeanUtil.copyToList(vo.getApproveNodes(), ApproveOrderNodeDto.class), ApproveOrderBusinessType.expenditureQuota, ead.getId(), ead.getQuotaCode(), null, this.getClass());
    }

    @Transactional
    @Override
    public void revocationExpenditureQuota(Long id) {
        ExpenditureQuotaDto dto = this.getById(id);
        Assert.notNull(dto, "找不到额度下达单");
        dto.setState(ExpenditureQuotaState.revocation.getKey());
        this.updateById(dto);
        approveOrderService.revocationApproveOrder(ApproveOrderBusinessType.expenditureQuota, id);
    }

    @Transactional
    @Override
    public void callbackAfterApprove(Long businessId, boolean isPass, boolean isFinalPass) {
        if (businessId == null)
            return;
        if (isPass) {
            if (isFinalPass) {
                ExpenditureQuotaDto ead = this.getById(businessId);
                ead.setState(ExpenditureQuotaState.pass.getKey());
                this.updateById(ead);
            }
        } else {
            ExpenditureQuotaDto ead = this.getById(businessId);
            ead.setState(ExpenditureQuotaState.reject.getKey());
            this.updateById(ead);
        }
    }
}
